<template>
  <div>
    <el-card shadow="hover">
      <CategorySelect :isShowList="isShowList"></CategorySelect>
    </el-card>
    <el-card shadow="hover" style="margin-top: 16px">
      <div v-show="isShowList">
        <el-button
          :disabled="!category3Id"
          type="primary"
          :icon="Plus"
          @click="showAddList"
          v-has="'btn.Attr.add'"
          >添加属性值</el-button
        >

        <el-table :data="attrList" border style="margin-top: 10px">
          <el-table-column
            type="index"
            label="序号"
            width="80"
            align="center"
          />
          <el-table-column prop="attrName" label="属性名称" width="160" />
          <el-table-column label="属性值">
            <template v-slot="{ row }">
              <el-tag
                style="margin-right: 5px"
                class="mx-1"
                size="small"
                v-for="item in row.attrValueList"
                :key="item.id"
                >{{ item.valueName }}</el-tag
              >
            </template>
          </el-table-column>
          <el-table-column label="操作" width="180">
            <template v-slot="{ row }">
              <el-button
                type="warning"
                size="small"
                :icon="Edit"
                @click="showEditList(row)"
                v-has="'btn.Attr.update'"
              ></el-button>

              <el-popconfirm
                :title="`是否确认要删除${row.attrName}?`"
                @confirm="deleteValue(row.id)"
              >
                <template #reference>
                  <el-button
                    type="danger"
                    size="small"
                    :icon="Delete"
                    v-has="'btn.Attr.remove'"
                  ></el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
      </div>
      <div v-show="!isShowList">
        <strong>属性名</strong>
        <el-input
          v-model="attr.attrName"
          style="width: 200px; margin-left: 15px"
          placeholder="请输入属性名"
        />

        <div style="margin: 20px 0">
          <el-button type="primary" :icon="Plus" @click="addAttrValue">
            添加属性值
          </el-button>
          <el-button @click="isShowList = true">取消</el-button>
        </div>

        <el-table :data="attr.attrValueList">
          <el-table-column
            type="index"
            label="序号"
            width="80"
            align="center"
          />
          <el-table-column label="属性值名称" prop="valueName">
            <template #default="{ row, $index }">
              <el-input
                size="small"
                ref="inputRef"
                @blur="toShow(row, $index)"
                v-if="row.isEdit"
                v-model="row.valueName"
              ></el-input>
              <div @click="toEdit(row)" v-else>
                <span>{{ row.valueName }}</span>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template #default="{ $index }">
              <el-button
                type="danger"
                size="small"
                :icon="Delete"
                @click="attr.attrValueList.splice($index, 1)"
              ></el-button>
            </template>
          </el-table-column>
        </el-table>
        <div style="margin: 20px 0">
          <el-button
            type="primary"
            @click="saveValueList"
            :disabled="isConfirmValue"
          >
            保存
          </el-button>
          <el-button @click="isShowList = true">取消</el-button>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script lang="ts">
  import { defineComponent } from "vue";
  export default defineComponent({
    name: "Attr",
  });
</script>
<script lang="ts" setup>
  import {
    deleteAttrApi,
    getAttrInfoListApi,
    saveAttrInfoApi,
  } from "@/api/product/attr";
  import type {
    attrListModel,
    attrModel,
    attrValueModel,
  } from "@/api/product/model/AttrModel";
  import { useCategoryStore } from "@/stores/category";
  import { Plus, Edit, Delete } from "@element-plus/icons-vue";
  import { ElMessage, type ElInput } from "element-plus";
  import { cloneDeep } from "lodash";
  import { storeToRefs } from "pinia";
  import { ref, watch, reactive, nextTick, onMounted, computed } from "vue";

  // 表格数据渲染
  const attrList = ref<attrListModel>([]);
  const { category1Id, category2Id, category3Id } = storeToRefs(
    useCategoryStore()
  );
  watch(category3Id, (val) => {
    if (val) {
      getAttrList();
    } else {
      attrList.value = [];
    }
  });

  async function getAttrList() {
    attrList.value = await getAttrInfoListApi({
      category1Id: category1Id.value as number,
      category2Id: category2Id.value as number,
      category3Id: category3Id.value as number,
    });
  }

  //切换 显示添加修改页面
  const isShowList = ref(true);
  const initAttr = () => ({
    attrName: "",
    attrValueList: [],
    categoryId: 0,
    categoryLevel: 3,
  });
  const attr = reactive<attrModel>(initAttr());
  const showAddList = () => {
    Object.assign(attr, initAttr());
    isShowList.value = false;
  };
  const showEditList = (row: attrModel) => {
    // 将当前指定的属性对象保存中attr中
    // 共享同一个attrValueList, 里面的attrValue也是同一个 => 修改时就直接修改
    // Object.assign(attr, row)
    // 解决办法: 使用lodash对row进行深拷贝
    Object.assign(attr, cloneDeep(row));
    isShowList.value = false;
    // attr.attrName = row.attrName;
    // attr.attrValueList = row.attrValueList;
  };

  // 显示页 删除
  const deleteValue = async (id: number) => {
    await deleteAttrApi(id);

    ElMessage.success("删除成功");
    getAttrList();
  };

  /* 编辑模式-点击属性值 切换input */

  // typeof: 得到类型
  // InstanceType: 得到实例的类型   ==> 指定ref中的value保存el-input组件对象
  const inputRef = ref<InstanceType<typeof ElInput>>();
  const toShow = (row: attrValueModel, index: number) => {
    // 如果没有名称, 失去焦点时存在一个空行  ==> 删除这个属性值对象
    if (!row.valueName) {
      attr.attrValueList.splice(index, 1);
      return;
    }
    // 如果与其它重名了, 失去焦点存在同名的2行 ==>  删除这个属性值对象
    // attr.attrValueList [{}, {valueName: 'a'}, {valueName: 'a'}]
    // 方式一: 如果有2个属性值对象的valueName等于row.valueName, 就重名了
    // const isRepeat = attr.attrValueList.filter(value => value.valueName===row.valueName).length===2
    // 方式二: 如果除了自己外, 还有一个的valueName等于row.valueName, 就重名了
    // const isRepeat = attr.attrValueList.some(item => item!=row && item.valueName===row.valueName)
    const isRepeat =
      attr.attrValueList.filter((item) => item.valueName === row.valueName)
        .length === 2;
    if (isRepeat) {
      attr.attrValueList.splice(index, 1);
      return;
    }
    row.isEdit = false;
  };
  //编辑模式
  const toEdit = (row: attrValueModel) => {
    row.isEdit = true;

    // 通过ref得到ElInput, 并调用其focus方法获得焦点
    // 不行: 更新数据后, dom是异步更新的, 直接同步获取不到更新后dom
    // inputRef.value?.focus()
    // 解决: 等到dom更新后再去获取 => 使用nextTick
    nextTick(() => {
      inputRef.value?.focus();
    });
  };

  //编辑模式 添加
  const addAttrValue = () => {
    const newAttrValue: attrValueModel = {
      valueName: "",
      attrId: attr.id,

      //切换编辑模式*
      isEdit: true,
    };

    attr.attrValueList.push(newAttrValue);

    nextTick(() => {
      inputRef.value?.focus();
    });
  };

  //编辑模式 保存
  const saveValueList = async () => {
    attr.attrValueList.forEach((item) => delete item.isEdit);
    attr.categoryId = category3Id.value as number;

    await saveAttrInfoApi(attr);
    ElMessage.success("保存成功！");
    isShowList.value = true;
    getAttrList();
  };
  //编辑模式 禁用保存
  const isConfirmValue = computed(() => {
    //如果没有就返回false
    const hasName = !!attr.attrName;
    //如果没有就返回false
    const hasList = attr.attrValueList.some((item) => item.valueName);

    return !hasName || !hasList;
  });

  //初始化请求
  onMounted(() => {
    if (category3Id.value) {
      getAttrList();
    }
  });
</script>

<style lang="scss" scoped></style>
